|
Technical Q&ADV36 -
|
on MemAllocatePhysicallyContiguous size result = NewPtrSys(size) if result != nil then if LockMemoryContiguous(result, size) != noErr then previousResult = result; result = NewPtrSys(size) if result != nil then if LockMemoryContiguous(result, size) != noErr then DisposePtr(result) result = nil; end-if end-if DisposePtr(previousResult) end-if end-if return result end MemAllocatePhysicallyContiguous |
Note: |
This algorithm is not particularly smart about finding
physically contiguous memory. Specifically, the algorithm
only makes two attempts to find a physically contiguous
block. If both attempts fail,
MemAllocatePhysicallyContiguous
gives up and
returns an error. There may be plenty of memory, there may
even be plenty of physically contiguous memory, but
MemAllocatePhysicallyContiguous
won't find it.
There are a number factors that determine whether the
LockMemoryContiguous
call used by MemAllocatePhysicallyContiguous
succeeds.
PrepareMemoryForIO
in the NewWorld.
Your driver may encounter these discontinuities at boot time, depending on the hardware platform, the RAM configuration, the time your driver loads, and the amount of memory consumed by other drivers that loaded before you.
LockMemoryContiguous
that simply checks
whether the memory is physically contiguous and returns
cannotMakeContiguousErr
if it isn't. If you
try to get physically contiguous memory before VM loads
(or at any time on a system with VM disabled), you will
use this version of LockMemoryContiguous
.
LockMemoryContiguous
with a somewhat smarter
algorithm. If VM is enabled and you try to get physically
contiguous memory after VM loads, this new algorithm will
work harder to find a physically contiguous range of
memory. However, a request for a large block of
physically contiguous memory is still likely to fail.
In summary, the ability of the system to provide physically contiguous memory is extremely limited, and extremely sensitive to environmental factors.
That’s the bad news. The good news is that you can do things to work around this limitation:
kDriverIsLoadedUponDiscovery
flag. You can
then use the pre-allocated memory when your driver is
opened.
LockMemoryContiguous
algorithm.
MemAllocatePhysicallyContiguous
returning
nil
.
You will get best results by using a combination of these techniques. If your card gains significant performance benefits from using physically contiguous memory, you should try to allocate that memory using the techniques described above. If all your attempts to allocate physically contiguous memory fail, you should ultimately be prepared to enable the scatter/gather mode on your hardware.